;; =============================================================================
;; parser

(in-package :oali.core)

(defun read-expr-list-from-stream (stream)
  "reads expression list from a stream given using oali.core as a default package"
  
  (let ((prev-package *package*)
	(prev-readtable-case (readtable-case *readtable*))
	result)
    ;; make oali.core as a default package, make reader to be case sensitive
    (setf *package* (find-package :oali.core))
    ;;(setf (readtable-case *readtable*) :invert)

    ;; read expression from the stream given
    (setf result (read stream))
    
    ;; restore reader state
    (setf *package* prev-package)
    (setf (readtable-case *readtable*) prev-readtable-case)

    ;; return result
    result))

(defun parse (context source)
  "parses source given using context as internally maintained state"

  ;; convert source to s-expression
  (let ((expr-list (cond
		     ;; string source
		     ((stringp source) (read-expr-list-from-stream
					(make-string-input-stream source)))

		     ;; stream source
		     ((streamp source) (read-expr-list-from-stream source))

		     ;; accept cons as it is
		     ((consp source) source)

		     ;; unknown source type
		     (t (error "unknown expression")))))
    
    ;; use newly created context if null is given
    (if (null context)
	(setf context (create-context)))

    ;; parse expressions list
    (dolist (expr expr-list)
      (let ((token-id (car expr)) (args (cdr expr)))
	(parse-toplev context token-id args)))))

